#include "asm_utils.h"
#include "interrupt.h"
#include "stdio.h"
#include "program.h"
#include "thread.h"
#include "sync.h"

// 屏幕IO处理器
STDIO stdio;
// 中断管理器
InterruptManager interruptManager;
// 程序管理器
ProgramManager programManager;

Semaphore c1,c2,c3,c4,c5,haschop;//5个信号量,添加信号量haschop表示持有筷子的哲学家的数量

#define times1 1000000
#define times2 1000000

void philosp1(void *arg)
{
    while(true){
       unsigned int times=times1;
       printf("The first philosopher is thinking.\n");
       while(times){times--;}
       printf("The first philosopher is hungry.\n");
       haschop.P();
       c1.P();
       printf("The first philosopher has gotten the 1 chopstick.\n");
       times=times2;
       while(times){times--;};
       c5.P();
       printf("The first philosopher has gotten the 5 chopstick and begins to eat.\n");
       times=times1;
       while(times){times--;}
       c1.V();
       c5.V();
       
       haschop.V();
       printf("The first philosopher has finished eating.\n");
     }
}

void philosp2(void *arg)
{
    while(true){
       unsigned int times=times1;
       printf("The second philosopher is thinking.\n");
       while(times){times--;}
       printf("The second philosopher is hungry.\n");
       haschop.P();
       c2.P();
       printf("The second philosopher has gotten the 2 chopstick.\n");
       times=times2;
       while(times){times--;};
       c1.P();
       printf("The second philosopher has gotten the 1 chopstick and begins to eat.\n");
       times=times1;
       while(times){times--;}
       c2.V();
       c1.V();
       haschop.V();
       printf("The second philosopher has finished eating.\n");
     }
}

void philosp3(void *arg)
{
    while(true){
       unsigned int times=times1;
       printf("The third philosopher is thinking.\n");
       while(times){times--;}
       printf("The third philosopher is hungry.\n");
       haschop.P();
       c3.P();
       printf("The third philosopher has gotten the 3 chopstick.\n");
       times=times2;
       while(times){times--;};
       c2.P();
       printf("The third philosopher has gotten the 2 chopstick and begins to eat.\n");
       times=times1;
       while(times){times--;}
       c3.V();
       c2.V();
       haschop.V();
       printf("The third philosopher has finished eating.\n");
     }
}

void philosp4(void *arg)
{
    while(true){
       unsigned int times=times1;
       printf("The fourth philosopher is thinking.\n");
       while(times){times--;}
       printf("The fourth philosopher is hungry.\n");
       haschop.P();
       c4.P();
       printf("The fourth philosopher has gotten the 4 chopstick.\n");
       times=times2;
       while(times){times--;};
       c3.P();
       printf("The fourth philosopher has gotten the 3 chopstick and begins to eat.\n");
       times=times1;
       while(times){times--;}
       c4.V();
       c3.V();
       haschop.V();
       printf("The fourth philosopher has finished eating.\n");
     }
}

void philosp5(void *arg)
{
    while(true){
       unsigned int times=times1;
       printf("The fifth philosopher is thinking.\n");
       while(times){times--;}
       printf("The fifth philosopher is hungry.\n");
       haschop.P();
       c5.P();
       printf("The fifth philosopher has gotten the 5 chopstick.\n");
       times=times2;
       while(times){times--;};
       c4.P();
       printf("The fifth philosopher has gotten the 4 chopstick and begins to eat.\n");
       times=times1;
       while(times){times--;}
       c5.V();
       c4.V();
       haschop.V();
       printf("The fifth philosopher has finished eating.\n");
     }
}


void first_thread(void *arg)
{
    // 第1个线程不可以返回
    stdio.moveCursor(0);
    for (int i = 0; i < 25 * 80; ++i)
    {
        stdio.print(' ');
    }
    stdio.moveCursor(0);

    //cheese_burger = 0;
    c1.initialize(1);
    c2.initialize(1);
    c3.initialize(1);
    c4.initialize(1);
    c5.initialize(1);
    haschop.initialize(4);

    programManager.executeThread(philosp1, nullptr, "second thread", 1);
    programManager.executeThread(philosp2, nullptr, "third thread", 1);
    programManager.executeThread(philosp3, nullptr, "fourth thread", 1);
    programManager.executeThread(philosp4, nullptr, "fifth thread", 1);
    programManager.executeThread(philosp5, nullptr, "sixth thread", 1);

    asm_halt();
}

extern "C" void setup_kernel()
{

    // 中断管理器
    interruptManager.initialize();
    interruptManager.enableTimeInterrupt();
    interruptManager.setTimeInterrupt((void *)asm_time_interrupt_handler);

    // 输出管理器
    stdio.initialize();

    // 进程/线程管理器
    programManager.initialize();

    // 创建第一个线程
    int pid = programManager.executeThread(first_thread, nullptr, "first thread", 1);
    if (pid == -1)
    {
        printf("can not execute thread\n");
        asm_halt();
    }

    ListItem *item = programManager.readyPrograms.front();
    PCB *firstThread = ListItem2PCB(item, tagInGeneralList);
    firstThread->status = RUNNING;
    programManager.readyPrograms.pop_front();
    programManager.running = firstThread;
    asm_switch_thread(0, firstThread);

    asm_halt();
}

